package com.itjiange.reglg.utils;

import com.itjiange.reglg.common.ErrorCode;
import com.itjiange.reglg.common.RedisCode;
import com.itjiange.reglg.exception.BussinessException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * Redis工具类
 *
 * @author ItJiange
 * @date 2023/11/14
 */
@Slf4j
@Component
public class RedisUtils {

    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 将键值对存入到 redis 中
     * @param key
     * @param value
     * @param timeout 过期时间 单位 秒
     */
    public void setKV(String key, String value, int timeout) {
        redisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS);
    }

    /**
     * 将键值对持久化存入到 redis 中
     * @param key
     * @param value
     */
    public void setKV(String key, String value) {
        redisTemplate.opsForValue().set(key, value);
    }

    /**
     * 根据键从redis中获取值
     * @param key
     * @return
     */
    public String getValueByKey(String key) {
        return redisTemplate.opsForValue().get(key);
    }

    /**
     * 判断 Redis 中是否存在该 key
     * @param key
     * @return true - 存在 false - 不存在
     */
    public boolean ifHasKey(String key) {
        return redisTemplate.hasKey(key);
    }

    /**
     * 清除 Redis 中的记录
     * @param key
     * @return true - 删除成功 false - 删除失败
     */
    public boolean removeByKey(String key) {
        return redisTemplate.delete(key);
    }

    /**
     * 接口防刷
     * @return
     */
    public boolean isAllowFlush(String key) {
        if (!ifHasKey(key)) {
            setKV(key, "10", RedisCode.FLUSH_PORT.getTimeOut());
        }
        if (getValueByKey(key).equals(RedisCode.BLACK_IP.getPrefix())) {
            throw new BussinessException(ErrorCode.TOO_MANY_REQUEST, "你小子已经被拉黑了，24 小时后再访问，哈哈");
        }
        ValueOperations<String, String> operations = redisTemplate.opsForValue();
        String decrement = getValueByKey(key);
        if (!"0".equals(decrement)) {
            decrement = operations.decrement(key) + "";
            setKV(key, decrement + "", RedisCode.FLUSH_PORT.getTimeOut());
            log.info("防刷剩余次数为：{}", decrement);
            return true;
        }
        // 当规定时间内的访问次数归零后，拉入黑名单，一天内不允许访问
        setKV(key, RedisCode.BLACK_IP.getPrefix(), RedisCode.BLACK_IP.getTimeOut());
        return false;
    }

    /**
     * 次数减一
     * @param key
     * @param timeOut
     */
    public void subOne(String key, int timeOut) {
        String decrement = String.valueOf(redisTemplate.opsForValue().decrement(key));
        setKV(key, decrement, timeOut);
    }

    /**
     * 次数加一
     * @param key
     * @param timeOut
     */
    public void addOne(String key, int timeOut) {
        String increment = String.valueOf(redisTemplate.opsForValue().increment(key));
        setKV(key, increment, timeOut);
    }
}
